package com.ztmmm.module.paper.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ztmmm.common.consts.ExamContant;
import com.ztmmm.common.consts.PaperConst;
import com.ztmmm.common.consts.QuTypeConstant;
import com.ztmmm.common.enums.ApiErrorEnum;
import com.ztmmm.common.vo.ApiRest;
import com.ztmmm.exception.ServiceException;
import com.ztmmm.module.exam.entity.Exam;
import com.ztmmm.module.exam.entity.ExamRepo;
import com.ztmmm.module.exam.mapper.ExamMapper;
import com.ztmmm.module.exam.mapper.ExamRepoMapper;
import com.ztmmm.module.paper.entity.Paper;
import com.ztmmm.module.paper.entity.PaperQu;
import com.ztmmm.module.paper.entity.PaperQuAnswer;
import com.ztmmm.module.paper.mapper.PaperMapper;
import com.ztmmm.module.paper.mapper.PaperQuAnswerMapper;
import com.ztmmm.module.paper.mapper.PaperQuMapper;
import com.ztmmm.module.paper.service.IPaperService;
import com.ztmmm.module.qu.entity.Qu;
import com.ztmmm.module.qu.entity.QuAnswer;
import com.ztmmm.module.qu.mapper.QuAnswerMapper;
import com.ztmmm.module.qu.mapper.QuMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 试卷 服务实现类
 * </p>
 *
 * @author ztm
 * @since 2023-03-23
 */
@Service
public class PaperServiceImpl extends ServiceImpl<PaperMapper, Paper> implements IPaperService {

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private ExamRepoMapper examRepoMapper;

    @Autowired
    private QuMapper quMapper;

    @Autowired
    private PaperQuMapper paperQuMapper;

    @Autowired
    private QuAnswerMapper quAnswerMapper;

    @Autowired
    private PaperQuAnswerMapper paperQuAnswerMapper;

    private static List<String> ABC = Arrays.asList(new String[]{
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K","L","M","N","O","P","Q","R","S","T","U","V","W","X"
            ,"Y","Z"
    });


    @Override
    @Transactional
    public ApiRest<String> createPaper(String examId) {


        String userId = "1";


        Exam exam = examMapper.selectById(examId);
        if(exam == null){
            throw new ServiceException(ApiErrorEnum.EXAM_NOT_EXIT.getMsg());
        }
        Integer timeLimit = exam.getTimeLimit();
        if(timeLimit == ExamContant.LIMIT){
            Date startTime = exam.getStartTime();
            Date endTime = exam.getEndTime();
            Date now = new Date();
            int compare = DateUtil.compare(now,startTime);
            int compare1 = DateUtil.compare(now,endTime);
            if(compare == -1){
                throw new ServiceException(ApiErrorEnum.EXAM_NOT_START.getMsg());
            }

            if(compare1 == 1){
                throw new ServiceException(ApiErrorEnum.EXAM_FINISHED.getMsg());
            }
        }

        if(exam.getState() == ExamContant.CLOSE){
            throw new ServiceException(ApiErrorEnum.EXAM_FINISHED.getMsg());
        }

        //判断试卷是否已经存在
        LambdaQueryChainWrapper<Paper> queryChainWrapper = new LambdaQueryChainWrapper<>(this.baseMapper);

        List<Paper> paperList = queryChainWrapper.eq(Paper::getExamId, examId)
                .eq(Paper::getUserId, userId).list();
        if(!CollUtil.isEmpty(paperList)){
            return ApiRest.success(paperList.get(0).getId());
        }

        //
        Paper paper = new Paper();
        paper.setId(IdWorker.getIdStr());
        paper.setCreateTime(new Date());
        paper.setExamId(examId);
        paper.setState(PaperConst.ING);

        //
        LambdaQueryChainWrapper<ExamRepo> examRepoLambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(examRepoMapper);
        List<ExamRepo> examRepoList = examRepoLambdaQueryChainWrapper.eq(ExamRepo::getExamId, examId).list();
        boolean hasJDT = false;
        int subScore = 0;
        for(ExamRepo item : examRepoList){
            if(item.getJdtCount() >= 1){
                hasJDT = true;
            }
            if(item.getJdtCount() >= 1){
//                Integer radioCount = item.getRadioCount();
//                Integer radioScore = item.getRadioScore();
                subScore += (item.getJdtScore()*item.getJdtCount());
            }

        }
        paper.setHasSaq(hasJDT?PaperConst.HASSAQ:PaperConst.NOSAQ);
        //考试时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(paper.getCreateTime());
        calendar.add(Calendar.MINUTE,exam.getTotalTime());
        paper.setLimitTime(calendar.getTime());

        paper.setObjScore(exam.getTotalScore() - subScore);
        paper.setSubjScore(subScore);
        paper.setQualifyScore(exam.getQualifyScore());
        paper.setUserTime(0);
        paper.setUserScore(0);
        paper.setUpdateTime(new Date());
        paper.setTitle(exam.getTitle());
        paper.setUserId(userId);
        this.baseMapper.insert(paper);

        //组卷
        List<Qu> qus = repoRandQu(examId);
        List<PaperQu> paperQuList = qus.stream().map(qu->{
            PaperQu paperQu = new PaperQu();
            paperQu.setId(IdWorker.getIdStr());
            paperQu.setQuId(qu.getId());
            paperQu.setPaperId(paper.getId());
            paperQu.setActualScore(0);
            paperQu.setAnswer("");
            paperQu.setAnswered(0);
            paperQu.setIsRight(0);//1正确0错误
            paperQu.setQuType(qu.getQuType());
            paperQu.setScore(qu.getScore());

            return paperQu;

        }).collect(Collectors.toList());

        int sort = 0;
        for (PaperQu paperQu : paperQuList) {
            if(paperQu.getQuType() == QuTypeConstant.RADIO){
                sort++;
                paperQu.setSort(sort);
            }
        }
        for (PaperQu paperQu : paperQuList) {
            if(paperQu.getQuType() == QuTypeConstant.MULTI){
                sort++;
                paperQu.setSort(sort);
            }
        }
        for (PaperQu paperQu : paperQuList) {
            if(paperQu.getQuType() == QuTypeConstant.JUDGE){
                sort++;
                paperQu.setSort(sort);
            }
        }
        for (PaperQu paperQu : paperQuList) {
            if(paperQu.getQuType() == QuTypeConstant.JDT){
                sort++;
                paperQu.setSort(sort);
            }
        }
        paperQuList.forEach(paperQu -> {
            paperQuMapper.insert(paperQu);
        });

        //每道题目的答案选项
        for (PaperQu paperQu : paperQuList) {
            //获取answers
            if(paperQu.getQuType() != QuTypeConstant.JDT){

                LambdaQueryChainWrapper<QuAnswer> quAnswerLambdaQueryChainWrapper
                        = new LambdaQueryChainWrapper<>(quAnswerMapper);
                List<QuAnswer> answerList
                        = quAnswerLambdaQueryChainWrapper.eq(QuAnswer::getQuId,paperQu.getQuId()).list();

                for (int i = 0; i < answerList.size(); i++) {
                    PaperQuAnswer paperQuAnswer = new PaperQuAnswer();
                    paperQuAnswer.setId(IdWorker.getIdStr());
                    paperQuAnswer.setPaperId(paper.getId());
                    paperQuAnswer.setAnswerId(answerList.get(i).getId());
                    paperQuAnswer.setChecked(0);
                    paperQuAnswer.setQuId(answerList.get(i).getQuId());
                    paperQuAnswer.setIsRight(answerList.get(i).getIsRight());
                    paperQuAnswer.setAbc(ABC.get(i));//a b c d e f g

                    paperQuAnswerMapper.insert(paperQuAnswer);
                }

            }
        }



        return ApiRest.success(paper.getId());
    }

    //组卷
    private List<Qu> repoRandQu(String examId){

        //获取exam repo 列表
        LambdaQueryChainWrapper<ExamRepo> examRepoLambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(examRepoMapper);
        List<ExamRepo> examRepoList = examRepoLambdaQueryChainWrapper.eq(ExamRepo::getExamId, examId).list();


        List<Qu> paperQus = new ArrayList<>();//存放

        List<Qu> exclues = new ArrayList<>();//去重

        for(ExamRepo examRepo : examRepoList){
            Integer radioCount = examRepo.getRadioCount();

            if(radioCount >= 1){
                //随机产生单选题
                //selct * from el_qu_repo
                List<Qu> radios = quMapper.repoRandQu(examRepo.getRepoId(), QuTypeConstant.RADIO, radioCount,exclues);
                for (Qu radio : radios) {
                    radio.setScore(examRepo.getRadioScore());
                    paperQus.add(radio);
                    exclues.add(radio);
                }
            }
            Integer multiCount = examRepo.getMultiCount();

            if(multiCount >= 1){
                //随机产生单选题
                //selct * from el_qu_repo
                List<Qu> multis = quMapper.repoRandQu(examRepo.getRepoId(), QuTypeConstant.MULTI, multiCount,exclues);
                for (Qu m : multis) {
                    m.setScore(examRepo.getMultiScore());
                    paperQus.add(m);
                    exclues.add(m);
                }
            }
            Integer judgeCount = examRepo.getJudgeCount();
            if(judgeCount >= 1){
                //随机产生单选题
                //selct * from el_qu_repo
                List<Qu> judges = quMapper.repoRandQu(examRepo.getRepoId(), QuTypeConstant.JUDGE, judgeCount,exclues);
                for (Qu j : judges) {
                    j.setScore(examRepo.getJudgeScore());
                    paperQus.add(j);
                    exclues.add(j);
                }
            }
            Integer jdtCount = examRepo.getJdtCount();
            if(jdtCount >= 1){
                //随机产生单选题
                //selct * from el_qu_repo
                List<Qu> jdts = quMapper.repoRandQu(examRepo.getRepoId(), QuTypeConstant.JDT, jdtCount, exclues);
                for (Qu jdt : jdts) {
                    jdt.setScore(examRepo.getJdtScore());
                    paperQus.add(jdt);
                    exclues.add(jdt);
                }
            }
        }
        return paperQus;
    }
}
